#include "menu.h"
#include "text.h"

#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>

#include <stdint.h>

SDL_Texture *renderText(const char *message, TTF_Font *font, SDL_Color color, SDL_Renderer *renderer) {
    SDL_Surface *surf = TTF_RenderText_Blended(font, message, color);
    if (surf == nullptr) {
        return nullptr;
    }
    SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surf);
    SDL_FreeSurface(surf);
    return texture;
}

#if defined(_WIN32)
#include <windows.h>
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
#else
int main(int argc, char *argv[]) {
#endif
    enum {
        SCREEN_WIDTH = 1280,
        SCREEN_HEIGHT = 720,
    };
    SDL_Window *win;
    SDL_Renderer *ren;
    TTF_Font *font;
    SDL_Texture *tex = nullptr;
    SDL_Color color = { 255, 255, 255, 255 };
    int quit = 0;
    SDL_GameController *gamepad = nullptr;
    static const char *fontFile =
#if defined(__linux__)
        "/usr/share/fonts/ttf/LiberationMono-Regular.ttf"
#else
        "C:/Windows/Fonts/cour.ttf"
#endif
        ;
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) {
        return -1;
    }
    if (TTF_Init() != 0){
        SDL_Quit();
        return -1;
    }
#if defined(__linux__)
    SDL_GameControllerAddMapping("030000004c050000da0c000011010000,Sony Interactive Entertainment Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftx:a0,lefty:a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,");
#endif
#if defined(_WIN32)
    SDL_GameControllerAddMapping("030000004c050000da0c000000000000,Controller,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,lefttrigger:b4,righttrigger:b5,");
#endif

    if (TTF_Init() != 0){
        SDL_Quit();
        return -1;
    }
    int nJoysticks = SDL_NumJoysticks();
    for (int i = 0; i < nJoysticks; i++) {
        if (SDL_IsGameController(i)) {
            gamepad = SDL_GameControllerOpen(i);
            break;
        }
    }
#if defined(__arm__)
    win = SDL_CreateWindow("", 0, 0, 1280, 720, SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN);
#else
    win = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
#endif
    if (win == nullptr) {
        TTF_Quit();
        SDL_Quit();
        return -1;
    }
    ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    if (ren == nullptr) {
        TTF_Quit();
        SDL_DestroyWindow(win);
        SDL_Quit();
        return -1;
    }
    font = TTF_OpenFont(fontFile, 24);
    if (font == nullptr) {
        TTF_Quit();
        SDL_DestroyRenderer(ren);
        SDL_DestroyWindow(win);
        SDL_Quit();
        return -1;
    }
    Menu menu(ren, font, 30, AlignHCenter);
    menu.addButton("abceee");
    menu.addButton("defz");
    menu.addButton("ghi");
    while (!quit) {
        SDL_Event e;
        while (SDL_PollEvent(&e)) {
            switch (e.type) {
                case SDL_QUIT:
                    quit = 1;
                    break;
                case SDL_KEYDOWN: {
                    char str[256];
                    if (tex) {
                        SDL_DestroyTexture(tex);
                    }
                    snprintf(str, 256, "KeyCode %02X %02X", e.key.keysym.scancode, e.key.keysym.sym);
                    tex = renderText(str, font, color, ren);
                    break;
                }
                case SDL_CONTROLLERBUTTONDOWN: {
                    char str[256];
                    if (tex) {
                        SDL_DestroyTexture(tex);
                    }
                    snprintf(str, 256, "Joy pressed: %02X %02X", e.cbutton.which, e.cbutton.button);
                    tex = renderText(str, font, color, ren);
                    if (e.cbutton.button == 5) quit = 1;
                    break;
                }
                case SDL_CONTROLLERAXISMOTION: {
                    char str[256];
                    if (e.caxis.value > -8000 && e.caxis.value < 8000) break;
                    if (tex) {
                        SDL_DestroyTexture(tex);
                    }
                    snprintf(str, 256, "Joy axis: %02X %02X %d", e.caxis.which, e.caxis.axis, e.caxis.value);
                    tex = renderText(str, font, color, ren);
                    break;
                }
                case SDL_CONTROLLERDEVICEADDED: {
                    if (gamepad) break;
                    char str[256];
                    if (tex) {
                        SDL_DestroyTexture(tex);
                    }
                    gamepad = SDL_GameControllerOpen(e.cdevice.which);
                    snprintf(str, 256, "Joy added: %02X", e.cdevice.which);
                    tex = renderText(str, font, color, ren);
                    break;
                }
                case SDL_CONTROLLERDEVICEREMOVED: {
                    if (!gamepad || SDL_GameControllerFromInstanceID(e.cdevice.which) != gamepad) break;
                    char str[256];
                    if (tex) {
                        SDL_DestroyTexture(tex);
                    }
                    SDL_GameControllerClose(gamepad);
                    gamepad = nullptr;
                    snprintf(str, 256, "Joy removed: %02X", e.cdevice.which);
                    tex = renderText(str, font, color, ren);
                    break;
                }
                default:
                    break;
            }
        }
        SDL_RenderClear(ren);
        if (tex) {
            SDL_Rect rc;
            SDL_QueryTexture(tex, nullptr, nullptr, &rc.w, &rc.h);
            rc.x = (SCREEN_WIDTH - rc.w) / 2;
            rc.y = (SCREEN_HEIGHT - rc.h) / 2;
            SDL_RenderCopy(ren, tex, nullptr, &rc);
        }
        menu.render(SDL_Point{100, 100});
        SDL_RenderPresent(ren);
    }
    if (gamepad) {
        SDL_GameControllerClose(gamepad);
    }
    TTF_CloseFont(font);
    TTF_Quit();
    SDL_DestroyRenderer(ren);
    SDL_DestroyWindow(win);
    SDL_Quit();
    return 0;
}
